/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <Config.h>
#include <animate/Soul.h>
#include <lib3d/anim2d/Sequence.h>
#include <lib3d/anim2d/Sequence.h>
#include <CompilerFeatures.h>

namespace liba {
namespace lib3d {
namespace node {
class Animation2D;
} // namespace node
namespace anim2d {

class AnimatedSequences : public animate::Soul, public animate::Node, public xml::ObjectANSI
{
public:
	static const Atom START_ANIMATION;

	AnimatedSequences( const Atom & name );
	AnimatedSequences(const AnimatedSequences& rhs);
	virtual ~AnimatedSequences();

	//designed for positive and negative time cycles
	virtual void LifeCycle(time_float delta_time) LIBA_OVERRIDE;

	void render_to_list( hard::Hardware * hardware, hard::RenderTexture * render_texture );

	//will remove itself from animate::Soul, you have to call life_cycle manually
	void set_manual_time_control(bool manual);

	void set_time(double time);

	size_t get_frame_number() const;
	double get_animation_length() const;
	bool needs_life_cycle() const;

	bool start_animation(const Atom & name);

	static const Atom start_name;
	static const Atom frame_percent_name;
	static const Atom frame_number_name;
	static const Atom current_time_name;

	bool is_finished()const
	{
		return anim_finished;
	}

	bool is_active_sequence()const
	{
		return active_sequence;
	}

	double get_height()const
	{
		return active_sequence ? active_sequence->get_height() : 0;
	}
	double get_width()const
	{
		return active_sequence ? active_sequence->get_width() : 0;
	}

	size_t get_frames_count()const
	{
		return active_sequence ? active_sequence->get_frames_count() : 0;
	}
	
	Atom get_animation_name()
	{
		return active_sequence ? active_sequence->get_name() : Atom();
	}

	void disable_loop();

	size_t GetSequencesCount()
	{
		return sequences.size();
	}

	anim2d::AbstractSequence * GetSequence(size_t index)
	{
		if (index >= GetSequencesCount())
			return NULL;
		
		Sequences::const_iterator itr = sequences.begin();
		for(size_t i = 0; i < index; i++)
			++itr;

		return *itr;
	}

	const std::string& GetStartSequence() const
	{
		return anim_to_start;
	}

	void SetStartSequence(const std::string & value)
	{
		anim_to_start = value;
	}

	std::list< anim2d::AbstractSequence* >::iterator SequencesBegin()
	{
		return sequences.begin();
	}

	std::list< anim2d::AbstractSequence* >::iterator SequencesEnd()
	{
		return sequences.end();
	}

	void AddSequence(anim2d::AbstractSequence * sequence)
	{
		sequences.push_back(sequence);
	}

	void RemoveSequence(anim2d::AbstractSequence * sequence)
	{
		if(active_sequence == sequence)
			active_sequence = NULL;

		delete sequence;
		sequences.erase(std::find(sequences.begin(), sequences.end(), sequence));
	}

	void SetFramePercent(double value);
	void SetFrameNumber(double value);
public:
	virtual bool on_node( xml::Provider * prov, const std::string & name );
	virtual bool on_attribute( xml::Provider * prov, const std::string & name, const std::string & value );
	virtual bool on_end_node( xml::Provider * prov );
	virtual void on_save_nodes(xml::SaverBase * saver) const;
private:
	typedef std::list< anim2d::AbstractSequence* > Sequences;
	Sequences sequences;
	anim2d::AbstractSequence * active_sequence;
	properties::DependencyProperty<double> currentTime;
	properties::VirtualDependencyProperty<double> framePercent;
	properties::VirtualDependencyProperty<double> frameNumber;
	int current_loop_dir;
	std::string anim_to_start;
	bool anim_finished;

	properties::Command<Atom> startAnimation;
};

}
} // namespace lib3d
} // namespace liba
using namespace liba;

